using System;
using System.Collections.Generic;
using System.Linq;
using Foundry.Engine;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace Foundry.Graphics
{
	public class ParticleSystem : Modifier
	{
		private static readonly string ParticleVs=@"
#version 150

uniform mat4 Projection;
uniform mat4 View;
uniform mat4 Model;
uniform mat4 ModelViewProjection;

in	vec4 Pos;
in	float Size;
in	vec4 Color;

out	vec4 geo_color;
out	float geo_size;

void main()
{
	gl_Position = Pos * ModelViewProjection;
	geo_color = Color;
	geo_size = Size;
}
";
		
		private static readonly string ParticleGs = @"
#version 150

uniform mat4 Projection;
uniform mat4 View;
uniform mat4 Model;
uniform mat4 ModelViewProjection;

layout(points) in;

in vec4 geo_color[];
in float geo_size[];


layout(triangle_strip, max_vertices = 4) out;

out vec2 texcoord;
out vec4 color;

void main()
{
	mat4 vp = View * Projection;
	for(int i = 0; i < gl_in.length(); i++)
    {
		float s = geo_size[i] * 0.25;
    	gl_Position = (vec4(-s, -s, 0, 1) * vp) + gl_in[i].gl_Position;
		texcoord = vec2(0, 0);
		color = geo_color[i];
		EmitVertex();
    	gl_Position = (vec4(-s, s, 0, 1) * View * Projection) + gl_in[i].gl_Position;
		texcoord = vec2(1, 0);
		color = geo_color[i];
		EmitVertex();
    	gl_Position = (vec4(s, s, 0, 1) * View * Projection) + gl_in[i].gl_Position;
		texcoord = vec2(1, 1);
		color = geo_color[i];
		EmitVertex();
    	gl_Position = (vec4(s, s, 0, 1) * View * Projection) + gl_in[i].gl_Position;
		texcoord = vec2(0, 1);
		color = geo_color[i];
		EmitVertex();
		EndPrimitive();
    }
}

";
		
		private static readonly string ParticleFs = @"
#version 150

in vec2 texcoord;
in vec4 color;

out vec4 ColorOut;
		
void main()
{
	ColorOut = color;
}

";
		
		DefaultShader shader;
		VertexArray<ParticleType> va;
		public ParticleSystem ()
		{
		}
		
		public void Initialize()
		{
			shader = new DefaultShader(ParticleType.Descriptor,
			                           Shader.FromSource<VertexShader>(ParticleVs),
			                           Shader.FromSource<GeometryShader>(ParticleGs),
			                           Shader.FromSource<FragmentShader>(ParticleFs));
			shader.CompileAndLink();
			shader.MakeCurrent();
			shader.Projection.Value = Matrix4.CreateOrthographic(4, 4, -4, 4);//Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 3, 1.0f, .001f,32f);
			shader.Model.Value = Matrix4.Identity;
			shader.NormalMatrix.Value = Matrix4.Identity;
			shader.View.Value = Matrix4.Identity;
			shader.ModelViewProjection.Value = shader.View.Value * shader.Projection.Value;
			
			
			va= new VertexArray<ParticleType>();
			
			
		}
		private static readonly Random rnd=new Random();
		private static IEnumerable<ParticleType> GenerateVertices(int count)
		{
			
			for(int i = 0; i < count; i++)
			{
				yield return new ParticleType()
				{
					Pos = new Vector4((float)rnd.NextDouble() * 2 - 1, (float)rnd.NextDouble() * 2 - 1, (float)rnd.NextDouble() * 2 - 1, 1),
					Color = new Color4((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble(), 1),
					Size = (float)rnd.NextDouble()
				};
			}
		}			
		
		
		public void Draw()
		{
			shader.MakeCurrent();
			shader.Model.Value = (Parent as Transform).AbsoluteTransform;
			va.MakeCurrent();
			GL.DrawArrays(BeginMode.Points, 0, 99);
			
		}

	}
	
	[Descriptor]
	public struct ParticleType
	{
		public static readonly VertexDescriptor Descriptor = new Foundry.Graphics.VertexDescriptor(typeof(ParticleType));
		public Vector4 Pos;
		public float Size;
		public Color4 Color;		
	}
}

